<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <title>调用栈动画演示 - 异度之刃X 卖凡矿</title>
  <style>
    body {
      font-family: monospace;
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      height: 100vh;
      background: #f0f0f0;
    }
    .stack-container {
      border: 2px solid #333;
      border-radius: 8px;
      background: #fafafa;
      padding: 10px;
      box-shadow: inset 0 0 10px rgba(0,0,0,0.1);
    }
    .stack {
      display: flex;
      flex-direction: column-reverse;
      align-items: center;
      width: 320px;
      min-height: 300px;
    }
    .frame {
      width: 280px;
      padding: 10px;
      margin: 5px 0;
      text-align: left;
      background: white;
      border-radius: 8px;
      box-shadow: 0 2px 5px rgba(0,0,0,0.2);
      opacity: 1;
      transform: translateY(0);
      transition: opacity 0.5s ease, transform 0.5s ease;
    }
    .frame.enter {
      opacity: 0;
      transform: translateY(20px);
    }
    .frame.leave {
      opacity: 0;
      transform: translateY(-20px);
    }
    .address {
      font-size: 12px;
      color: gray;
    }
    .log {
      margin-top: 20px;
      width: 520px;
      height: 180px;
      background: #fff;
      border: 1px solid #ccc;
      border-radius: 8px;
      padding: 10px;
      overflow-y: auto;
      font-size: 14px;
    }
    .log-entry {
      margin: 2px 0;
    }
    .log-call {
      color: green;
      font-weight: bold;
    }
    .log-return {
      color: red;
      font-weight: bold;
    }
    .log-entry a {
      text-decoration: underline;
      cursor: pointer;
      color: blue;
    }
    button {
      margin: 10px;
      padding: 10px 20px;
      border: none;
      border-radius: 6px;
      background: #007bff;
      color: white;
      font-size: 16px;
      cursor: pointer;
    }
    button:hover {
      background: #0056b3;
    }
  </style>
</head>
<body>
  <div class="stack-container">
    <div class="stack" id="stack"></div>
  </div>
  <div style="text-align:center;">
    <button onclick="callFunction()">调用函数</button>
    <button onclick="returnFunction()">返回函数</button>
    <button onclick="autoDemo()">自动演示</button>
  </div>
  <div class="log" id="log"></div>

  <script>
    const stack = document.getElementById('stack');
    const log = document.getElementById('log');

    // 模拟异度之刃X 卖凡矿流程
    const functions = [
      "主程序",
      "找到背包里的凡矿",
      "检查数量是否足够",
      "执行卖出凡矿",
      "增加金币",
      "刷新界面"
    ];

    const descriptions = [
      "开始卖出流程",
      "找到凡矿 ×3",
      "数量足够，可以卖出",
      "卖出凡矿，获得 300G",
      "金币 +3000，总金币 1503000G",
      "界面刷新，库存更新"
    ];

    let callIndex = 0;

    function generateAddress(index) {
      return "0x" + (1000 + index * 16).toString(16).toUpperCase();
    }

    function addLog(message, type, index) {
      const entry = document.createElement('div');
      entry.className = `log-entry ${type}`;
      if (index !== undefined) {
        entry.innerHTML = `${message} <a onclick="highlightFrame(${index})">查看栈帧</a>`;
      } else {
        entry.textContent = message;
      }
      log.appendChild(entry);
      log.scrollTop = log.scrollHeight;
    }

    function highlightFrame(index) {
      const frames = document.querySelectorAll('.frame');
      const frame = frames[frames.length - 1 - index];
      if (frame) {
        frame.style.outline = '2px solid orange';
        setTimeout(() => {
          frame.style.outline = '';
        }, 1000);
      }
    }

    function callFunction() {
      if (callIndex < functions.length) {
        const frame = document.createElement('div');
        frame.className = 'frame enter';
        const addr = generateAddress(callIndex);
        frame.innerHTML = `<div class="address">${addr}</div><div>${functions[callIndex]}()</div>`;
        stack.appendChild(frame);

        void frame.offsetWidth;
        frame.classList.remove('enter');

        addLog(`调用 ${functions[callIndex]}() -> ${descriptions[callIndex]}`, "log-call", callIndex);
        callIndex++;
      }
    }

    function returnFunction() {
      if (stack.lastChild) {
        const frame = stack.lastChild;
        const funcName = functions[callIndex - 1];
        frame.classList.add('leave');
        addLog(`返回 ${funcName}() 出栈`, "log-return", callIndex - 1);
        callIndex--;
        setTimeout(() => {
          if (frame.parentNode) {
            stack.removeChild(frame);
          }
        }, 500);
      }
    }

    function autoDemo() {
      let steps = [];

      for (let i = 0; i < functions.length; i++) {
        steps.push(() => callFunction());
      }
      for (let i = 0; i < functions.length; i++) {
        steps.push(() => returnFunction());
      }

      let i = 0;
      const interval = setInterval(() => {
        steps[i]();
        i++;
        if (i >= steps.length) clearInterval(interval);
      }, 1200);
    }
  </script>
</body>
</html>